package com.jwater.core.net;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jwater.io.netty.channel.ChannelHandlerContext;
import jwater.io.netty.channel.SimpleChannelInboundHandler;
import jwater.io.netty.handler.timeout.IdleState;
import jwater.io.netty.handler.timeout.IdleStateEvent;
/**
 * @description:
 * @author: jnner
 * @createDate: 2021/2/5
 * @version: 1.0
 */
public class NettyClientHandler extends SimpleChannelInboundHandler<NodePacket> {
	private static Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);
	private volatile boolean isConnect = false;
	private volatile String id;
	private ChannelHandlerContext ctx;
	protected NettyClient nettyClient;

	public NettyClientHandler(NettyClient nettyClient) {
		this.nettyClient = nettyClient;
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		this.ctx = ctx;
		isConnect = true;
		if (nettyClient.node != null) {
			nettyClient.node.setConnect(true);
			if (nettyClient.nodeHandler != null) {
				NetExecutorUtils.execute(() -> {
					nettyClient.nodeHandler.onConnect(nettyClient.node);
				});
			}
		}
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		isConnect = false;
		if (nettyClient.node != null) {
			nettyClient.node.setConnect(false);
			if (nettyClient.nodeHandler != null) {
				nettyClient.nodeHandler.onDisconnect(nettyClient.node);
			}
			NetExecutorUtils.execute(() -> {
				nettyClient.node.doClientDiconnect();
			});
		}
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof IdleStateEvent) {
			if (((IdleStateEvent) evt).state() == IdleState.READER_IDLE) {
				ctx.disconnect();
			}
		}
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, NodePacket packet) throws Exception {
		if (nettyClient.node != null) {
			nettyClient.node.doHandler(packet);
		}
	}

	public void setId(String id) {
		this.id = id;
	}

	public void waitConnectSuccess() {
		// 连接成功后，等待channelActive方法调用成功isConnect发生变化，线程自旋等待，等待时间是很短的
		while (!isConnect) {
		}
	}

	public void write(NodePacket packet) {
		if (isConnect) {
			this.ctx.writeAndFlush(packet);
		} else {
			logger.warn("write error,not connect for:" + id);
		}
	}

	public void close() {
		if (this.ctx != null) {
			this.ctx.close();
		}
	}
}
